package com.crcc.materialinventory.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.crcc.common.exception.BaseResultInfoInterface;
import com.crcc.common.exception.ResultBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * @author dongy
 * @Description:
 * @create 2021-03-24
 */
@Component
public class TokenInterceptor implements HandlerInterceptor {
	private String[] keyExclusions = {"time", "sign"};
	private final long time = 30000;//30秒钟
	private final String salt = "yyyy5616MMdd";
	private static final Logger logger = LoggerFactory.getLogger(TokenInterceptor.class);


	//这个方法是在访问接口之前执行的，我们只需要在这里写验证登陆状态的业务逻辑，就可以在用户调用指定接口之前验证登陆状态了
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		//如果是 OPTIONS 请求，让 OPTIONS 请求返回一个200状态码
		//vue每个请求第一次为OPTIONS,需要跳过
//		if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
//			response.setStatus(HttpServletResponse.SC_OK);
//			return true;
//		}
//
//		UnToken annotation = null;
//		if(handler instanceof HandlerMethod) {
//			annotation = ((HandlerMethod) handler).getMethodAnnotation(UnToken.class);
//		}
//
//		//有声明不需要权限
//		if(annotation != null){
//			return true;
//		}else{
//			String token = request.getHeader("Authorization");
//			if(StringUtils.isBlank(token)){
//				returnJson(request,response, ExceptionEnum.TOKEN_NOT_EXIT);
//				return false;
//			}
//
//			Object obj = JwtUtils.getInstance().check(token);
//			if (obj == null){
//				returnJson(request,response, ExceptionEnum.TOKEN_NOT_EXIT);
//				return false;
//			}else {
//				Object userInfoIdObj = JwtUtils.getInstance().check(token).get("user_info_id");
//				if (userInfoIdObj == null){
//					returnJson(request,response, ExceptionEnum.TOKEN_NOT_EXIT);
//					return false;
//				}
//
//				ICUserService iCUserService = getBean(ICUserService.class,request);
//				QueryWrapper queryWrapper = new QueryWrapper();
//				queryWrapper.inSql("user_info_id", "select user_info_id from c_user where user_info_id = '" + userInfoIdObj.toString() + "'");
//				CUser cUser = iCUserService.getOne(queryWrapper);
//				if(cUser==null) {
//					returnJson(request,response,ExceptionEnum.TOKEN_NOT_EXIT);
//					return false;
//				}
//			}
//		}

		return true;
	}

	//获取dao,拦截器中只能通过webapplicationcontextutils获取spring boot中的bean.
	private <T> T getBean(Class<T> t, HttpServletRequest request) {
		BeanFactory beanFactory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
		return beanFactory.getBean(t);

	}

	private void returnJson(HttpServletRequest request, HttpServletResponse response, BaseResultInfoInterface errorInfo) {
		PrintWriter writer = null;
		String headerOrigin = request.getHeader("origin");
		if (headerOrigin != null) {
			response.setHeader("Access-Control-Allow-Origin", headerOrigin);
		}
		response.setHeader("Access-Control-Expose-Headers", "page, per_page,status,total_count");
		response.setHeader("Access-Control-Allow-Credentials", "true");
		response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
		response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE,PUT");
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json; charset=utf-8");
		try {
			//			response.setStatus(401);
			writer = response.getWriter();
			writer.print(JSONObject.toJSONString(ResultBody.error(errorInfo)));
		} catch (IOException e) {
			logger.error("过滤器输出流异常" + e);
		} finally {
			if (writer != null) {
				writer.close();
			}
		}
	}

	/**
	 * 私有方法：获取时间戳或签名数据
	 *
	 * @param request
	 * @param type
	 * @return
	 */
	private String getTimeOrSign(HttpServletRequest request, String type) {
		Map map = request.getParameterMap();
		for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); ) {
			Map.Entry element = (Map.Entry) iter.next();
			Object key = element.getKey();
			String[] strArr = (String[]) element.getValue();
			if (key.toString().equals(type)) {
				return strArr[0];
			}
		}

		return null;
	}

	/**
	 * 私有方法：验证key是否是sign或time字符串，不是返回true
	 *
	 * @param key
	 * @return
	 */
	private boolean isNoKey(String key) {
		for (String exclusion : keyExclusions) {
			if (key.equals(exclusion)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 私有方法：验证时间戳
	 *
	 * @param time
	 * @return
	 */
	private boolean verifyTime(String time) {
		if (time == null || "NaN".equals(time)) {
			return false;
		}
		long time1 = System.currentTimeMillis();
		if (Math.abs(time1 - Long.valueOf(time)) <= this.time) {
			return true;
		}
		return false;
	}

	/**
	 * 私有方法：验证签名数据
	 *
	 * @param request
	 * @param sign
	 * @return
	 */
//	private boolean verifySign(HttpServletRequest request, String sign) {
//		if (sign == null) return false;
//		StringBuffer sb = new StringBuffer();
//		SortedMap<Object, Object> parameters = getSortedMap(request);
//		Set<?> es = parameters.entrySet();
//		Iterator<?> it = es.iterator();
//		while (it.hasNext()) {
//			Map.Entry entry = (Map.Entry) it.next();
//			String k = (String) entry.getKey();
//			String v = (String) entry.getValue();
//			if (!"sign".equals(k)) {
//				sb.append(k + "=" + v + "&");
//			}
//		}
//		if (sb.toString().equals(""))
//			sb.append("&");
//		sb.append(UtilDate.formatDate(new Date(), salt));
//		String time = getTimeOrSign(request, "time");
//		sb.append("&time=" + time);
//		return sign.toLowerCase().equals(UMD5.encodeMD5(sb.toString(), "UTF-8").toLowerCase());
//	}

	/**
	 * 私有方法：根据请求参数获取排序Map
	 *
	 * @param request
	 * @return
	 */
	private SortedMap getSortedMap(HttpServletRequest request) {
		SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
		Map map = request.getParameterMap();
		for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); ) {
			Map.Entry element = (Map.Entry) iter.next();
			Object key = element.getKey();
			String[] strArr = (String[]) element.getValue();
			if (isNoKey(key.toString())) {
				if (strArr != null && strArr.length > 0) {
					parameters.put(key, strArr[0]);
				}
			}
		}
		return parameters;
	}

}